DOC 1.1 -- Documentation for MLDL106A/B.LIB in the HACKER directory

NOTE!  This is a plain ASCII text file containing multiple
documents. You may find it most convenient to view or print this file
by running the DOC.EXE program (supplied on this disk) on your PC.
This is the first Goodies Disk to do it this way.  Hope you like it.

:GD9
:MLDL 1.06 A/B
:-jkh-
@@MLDL 1.06 A/B
MLDL 1.06A/B, OCTOBER 1991  -- S/SX ONLY!

Machine Language Development Library
by Jan Brittenson

This entire document is for a single library in the
HACKER directory, of which there are two versions:

MLDL106A.LIB
MLDL106B.LIB

This is an improved version of the MLDL on Goodies Disk
#3, with much more complete documentation. Note that
there are two versions, the A version which runs from RAM
only, and does not work if it's in a ROM or
write-protected RAM card; and the B version, which ONLY
works in a ROM or write-protected RAM card (this version
used to be a commercial product but was recently placed
in the public domain). Otherwise the A and B versions
are identical. Use the appropriate one. If you try to
use one and get a "Fatal Error: Card Failure" message,
then try the other one. -jkh-

   The MLDL is a Machine Language Development Library for
the HP-48SX, and as such is primarily intended for HP-48
Machine-Language Programmers familiar with the following:

        o  The Saturn instruction set

        o  Assembler programming

        o  Machine code debugging

        o  RPL internals - GC (Garbage Collection);
           system RPL; PMC (Prefixed Machine Code)

The MLDL disassembles HP48 machine language into assembly
language using AG mnemonics, not HP mnemonics. AG
mnemonics are named after Alonzo Gariepy, who designed
his mnemonic vocabulary explicitly to resemble the
mnemonics of other commonly used processors. Hewlett
Packard also has a set of mnemonics, described in files
bundled with their unsupported development tools [Goodies
Disk #4  -jkh-]. The HP mnemonics set and assembler
syntax do not adhere to a source-destination model.
Instructions sometimes span over several lines, it is
column-oriented, and is by some people perceived as
somewhat unfriendly.

[If you are more used to the HP mnemonics, see the
ROSETTA.DOC file in the HACKER directory on this disk; it
is a complete AG <--> HP translation table. Use LIST.COM
to view and/or print it. -jkh-]

Thanks to Alonzo Gariepy for his restructuring of the
Saturn instruction set, to Rick Grevelle and Joe Ervin
for their continuous testing and helpful advice, and to
everyone near and far who has contributed  to charting
the HP48 internals.
@@Installing
INSTALLING THE LIBRARY


   The MLDL consists of five named commands, and has been
given the number 1092 decimal (hexadecimal 444). To
install it, transfer the A or B version of the binary
file to your calculator and store it in a suitable port.
Turn the calculator off, then back on. It will
automatically attach to the HOME directory.

To remove it, go to the directory where you previously
attached it, enter `:p:1092', press DUP DETACH, then
PURGE. The library does not automatically attach.

   The display will flicker once as the library gets
purged from the port.
@@Commands
LIBRARY COMMANDS


The MLDL library contains five commands:

ABOUTMLDL ============================ the "about" screen
MLDB ============== interactive Machine Language DeBugger
MLPR ====== Machine Language PRint disassembly (ON exits)
ML1 ==== Machine Language disassembly, 1 instruction only
MLOPC =========================== Machine Language OPCode

These five commands are described in detail below.
Note: they have equal signs (==) next to them in the DOC
viewer's selection column for quick identification.
@@ABOUTMLDL====
[ABOUTMLDL] =============================================

Displays version and copyright. [Note: Jan released MLDL
to the public domain; it may be freely copied. -jkh-]
@@MLDB=========
[MLDB] ==================================================

   HP48 ML Debugger. This description covers the MLDB
local mode. It can also operate in one of two server
modes: interactive or protocol, described under MLDB
Server Modes below. In Local Mode, the HP-48 display and
keyboard, are used to control the debugger. In Server
Mode, control is maintained via the serial port, either
from a dumb ASCII terminal (Interactive Mode), or a
dedicated front-end (Protocol Mode). To insure that MLDB
is in Local Mode when invoked, clear user flags 32 and
33:

        32 33 CF CF

   MLDB allows you single-step ML programs, as well as
examine registers and memory contents. Since it
single-steps ML, it is not useful for debugging RPL code
-- unless you wish to follow your RPL thread on an ML
level.

When invoked, an argument in expected in level 1:

        Global name (variable)

                The value of the global name is
            recursively used as an argument. Caution: The
            value can be another global name, whose value
            is then used in turn. If the variable's value
            is its own name, and endless recursion will
            occur. Such a recursion can be aborted woth
            ON-C.

        Code object

                MLDB halts before the first instruction
            of the code object. Both the PC and A
            registers are set to the address of the first
            instruction.

        XLIB

               The XLIB must be a code object, which
            becomes the argument.

        Binary integer

                MLDB treats the binary integer as the
            address of a prefixed machine code routine
            (PMC). It halts at the first instruction of
            the PMC. PMCs consist of a 5-nibble pointer
            to the first instruction which is usually,
            but not always, the address of the PMC plus
            5.
            
        @#3a81 (True)

                If the token following the MLDB
            invocation is a code object, MLDB halts at
            its first instruction. Any other type of
            object results in an error. When the code
            object completes, RPL execution continues
            with the next consecutive word. When the
            argument is @#3ac0 (False), the invocation of
            MLDB is ignored, so the invocation can be
            preceded by a test -- for instance a user
            flag test, which permits the debugging of
            individual machine language objects embedded
            in RPL programs to be turned on and off by
            setting user flags.

        Any object other than @#3a81

                Other objects are ignored -- the debugger
            returns immediately. Included here is @#3ac0
            (False).
@@The 8 Screens
The 8 Screens


   The Local Mode MLDB uses PICT (the graphical display)
to present information. Since all information will not
fit on one display at once, it has been divided into 8
screens. Only one screen is active at any one time.
Switching between screens is done by means of the 6 menu
keys, here referred to as A-F, which correspond to screen
1 through 6 respectively, and the MTH and VAR keys, which
correspond to screens 7 and 8.

   The sample screens 1-8 below are from the PMC at
#59CC, and can be approximately reproduced by:

        #59CCh MLDB

    Note: some MLDL commands (viz. MLDB, ML1, and MLPR)
    automatically create an 'MLDLpar' variable in the
    HOME directory. It contains configuration data and
    variables used. It is about 650 bytes. Depending on
    the number of directories and variables in the HP48,
    a significant gain in speed can be achieved by
    reordering the HOME directory so the 'MLDLpar'
    variable appears last in the VAR menu. See the ORDER
    command in your HP48 manual for details on how to do
    this.

Note: The 8 screens have "" characters next to them in
the DOC viewer's selection column for quick
identification.
@@CPU State   
Screen 1  - General CPU State (key [A])

                                 Ŀ
Mnemonic........................ CALL.4 #0679B         
Opcode..........................  8E4CD0               
PC, P, Carry, Hex/Dec mode, ST.. @:059D1 P:0 CH ST:218 
A.A and C.A..................... A:000CC C:77794       
B.A, D.A, and HST............... B:729A9 D:00F96 HST:2 
D0 and 6 bytes @D0.............. D0:409C1/9540A8240BC9 
D1 and 6 bytes @D1.............. D1:77799/000000000000 
Top 3 levels of RSTK............ RST:00000:00000:00000 
                                 
Notes:

"Mnemonic" is the current instruction, pointed to by the
PC (program counter). "Opcode" is the current machine
language instruction, in hex. The third line is the
current PC, P register, the status of the carry bit (a C
if carry is set, and a blank if clear), current hex/dec
mode (D = DEC mode, H = HEX mode) as set by the SETDEC
and SETHEX instructions, and the low three nibbles of the
ST register. These three lines are common to many of the
MLDB screens described below.

Lines four and five are the low five nibbles (the .A
field) of the A, B, C, and D registers, as well as the
HST register. Lines six and seven are the D0 and D1
registers, as well as the contents of the addresses that
they point to, as 12-nibble integers. The address
pointed to by them is displayed as the rightmost digit,
with the next higher address pointing to the digit to its
left, and so on. This seems "backwards", but is done
this way because the Saturn CPU stores integers in memory
with the least significant digit (nibble) at the lowest
address, and the most significant digit at the highest
address, thus it is usually handier to view memory
contents backwards like this.

The bottom line is common to several of the screens
described below. It contains the top three RSTK (return
stack) levels.
@@Main Regs   
Screen 2  - Arithmetic registers (key [B])

                                 Ŀ
Mnemonic........................ CALL.4 #0679B         
Opcode..........................  8E4CD0               
PC, P, Carry, Hex/Dec mode, ST.. @:059D1 P:0 CH ST:218 
Register A...................... A:00000005444000CC    
Register B...................... B:000000000007611E    
Register C...................... C:000000000007792C    
Register D...................... D:00000000000004D0    
Top 3 levels of RSTK............ RST:00000:00000:00000 
                                 

Lines 4 to 7 are registers A, B, C, and D respectively.
All 16 nibbles (64 bits) are displayed.
@@Scratch Regs
Screen 3  - Data registers (key [C])

                                 Ŀ
Mnemonic........................ CALL.4 #0679B         
Opcode..........................  8E4CD0               
PC, P, Carry, Hex/Dec mode, ST.. @:059D1 P:0 CH ST:218 
Register R0..................... R0:053385D439800040   
Register R1..................... R1:00000005444059D1   
Register R2..................... R2:0000000000075BC1   
Register R3..................... R3:0000000544402E92   
Register R4..................... R4:00015075A6375AA1   
                                 

Lines 4 to 8 are registers R0, R1, R2, R3, and R4
respectively. All 16 nibbles (64 bits) are displayed.
@@Return Stack
Screen 4  - Return stack (key [D])

                                 Ŀ
Mnemonic........................ CALL.4 #0679B         
Opcode..........................  8E4CD0               
PC, P, Carry, Hex/Dec mode, ST.. @:059D1 P:0 CH ST:218 
                                                       
RSTK levels 0 and 4............. RST0:00000 RST4:00000 
RSTK levels 1 and 5............. RST1:00000 RST5:00000 
RSTK levels 2 and 6............. RST2:00000 RST6:00000 
RSTK levels 3 and 7............. RST3:00000 RST7:00000 
                                 

Lines 5 to 8 are the eight levels of RSTK, displayed as
5-nibble integers. RSTK0 is the top of the stack, and is
the most recent return address (or value most recently
PUSHed there).
@@Memory Dump 
Screen 5  - Memory dump (key [E])

                                 Ŀ
Locations 59A0-59AF............. 059A0:56113680913420CC
Locations 59B0-59BF............. 059B0:4E0156716FCC56FD
Locations 59C0-59CF............. 059C0:015B38D5E0101D95
Locations 59D0-59DF............. 059D0:08E4CD08E46C0101
Locations 59E0-59EF............. 059E0:D230574911191443
Locations 59F0-59FF............. 059F0:4E4A201101311456
Locations 5A00-5A0F............. 05A00:12280A50143174E7
Locations 5A10-5A1F............. 05A10:8E58D01311741431
                                 

The 128 addresses surrounding the current PC are
displayed, with the line corresponding to the current PC
at the center. The location of the current instruction is
indicated by an inverse digit (in this example, the "8"
at address 059D1). Each line is 16 nibbles, with the
leftmost nibble corresponding to the lowest address
("frontwards" order). The memory dump can be shifted one
nibble using the [CST] 4 option (see Option 4, below).
@@Instructions
Screen 6  - ML Instruction Stream (key [F])

                                 Ŀ
PC, P, Carry, Hex/Dec mode, ST.. @:059D1 P:0 CH ST:218 
Next 7 instructions............. CALL.40679B
                                  CALL.4 #06641        
                                  MOVE.W A,R1          
                                  CLR.A C              
                                  MOVE.P1 #5,C         
                                  CALL.3 #05B7D        
                                  MOVE.W R1,C          
                                 

The top line is the current PC, P register, the status of
the carry bit, HEX/DEC mode, and the low three nibbles of
the ST register.

The remaining seven lines are the seven subsequent
instructions, with the next instruction to be executed
always appearing in reverse video at the top of the
screen (here somewhat crudely illustrated with the 
character.)
@@Breakpoints 
Screen 7  - Breakpoint Table Screen (key MTH)

                                 Ŀ
Breakpoint #1...................  1:6100 +02           
Breakpoint #2...................  2:6104 -02           
Breakpoint #3...................  3:613A  00           
Breakpoints #4-#8: not set......  4:0000  00           
                                  5:0000  00           
                                  6:0000  00           
                                  7:0000  00           
                                  8:0000  00           
                                 

Each line corresponds to one breakpoint. There are eight
breakpoints, each consisting of an address and a counter.
The address is displayed immediately following the
breakpoint number. Trailing each line is the breakpoint
counter, a signed 2-nibble (8-bit) hex integer. Any
breakpoints at the current location are displayed in
reverse video.
@@Watchpoints 
Screen 8  - Watchpoint Table Screen (key VAR)

                                 Ŀ
Watchpoint #1................... 00138:9DEF0C1085D1BF21
Watchpoint #2................... 01400:8F235A05C965E186
Watchpoint #3................... FFFFF:12369B108DADF100
Watchpoint #4................... 70000:F3C5A0000FB13FB3
Watchpoints #5-#8: not set...... 00000:2369B108DADF1008
                                 00000:2369B108DADF1008
                                 00000:2369B108DADF1008
                                 00000:2369B108DADF1008
                                 

Each line corresponds to a watchpoint. A watchpoint can
be set to any arbitrary address. The display format is
consistent with the format of the memory dump screen.
@@Annunciators
The HP48 Annunciators


The display annunciators are left undisturbed by the
local mode MLDB. If in server mode, only the I/O
annunciator (the arrow in the upper right corner of the
display) is used; it will flicker with each character
received over the serial line. The annunciators are left
in whatever state the HP48 ROM put them in, which means
that the busy annunciator is usually lit and all other
annunciators are turned off. For all practical purposes,
as far as the HP48 ROM is concerned a system RPL program
is executing, even if it is temporarily halted between
instructions by MLDB.

The local mode MLDB puts the Saturn microprocessor in
light sleep between keystrokes, which means that battery
consumption is generally low even if the busy annunciator
is lit. Light sleep is not used when in server mode,
which always runs at full power.
@@Local Kbd
The Local Mode MLDB keyboard


   A number of keys will accept an argument, referred to
as ARG. To enter ARG, press [0] (the zero key) followed
by a hex number, which will make up ARG. It is restricted
to 5 hex digits (20 bits). When [0] is pressed, the
bottom display line, regardless of which screen is
currently active, becomes an ARG entry line:

        ARG:00000             
        

   This remains in effect until a non-hex key is pressed,
at which point that key is executed. Some keys behave
differently depending on whether ARG was present. [DEL],
for instance, does nothing, effectively cancelling ARG.
The backarrow, [<==], divides the argument by 16, in
effect shifting it right one digit. The argument is
always a 20-bit unsigned integer. The digits A-F are
found on the menu keys. The [+/-] key negates (2's
complement) the argument.


Example, ARG entry:

Keys           Comments        Bottom line following keys
                   
0              Start entry     ARG:00000             
5              Digit 5         ARG:00005             
7              Digit 7         ARG:00057             
[<==]          Shift right     ARG:00005             
9              Digit 9         ARG:00059             
D1             Digits D, 1     ARG:059D1             
[+/-]          Negate          ARG:FA62F             
000            Three 0s        ARG:2F000             
[<==]          Shift right     ARG:02F00             
[DEL]          Cancel ARG
@@Moving Around
Moving Around in Memory


Moving around is done with the arrow keys and the NXT
key. Notice that none of these keys actually execute the
previous instruction; only the PC is affected:

        [up]    Decrement PC by 16 (or 16*ARG)
        [down]  Increment PC by 16 (or 16*ARG)
        [left]  Decrement PC by 1 (or ARG)
        [right] Increment PC by 1 (or ARG)
        [NXT]   Move to next instruction (or ARG
                instructions forward)
        [ENTER] Set PC to ARG

In addition, there is a "mark":

        [x]     (Multiplication key)
                Set mark to ARG, if present. Otherwise
                the MARK is set to the current PC.

        [+/-]   Swaps the PC and the mark.



Example, Moving Around:

Keys            Effect           Display following keys
                      

   First, set the PC to 059D1:
                                Ŀ
059D1[ENTER]    PC=#059D1h      @:059D1 P:0 CH ST:218 
                                CALL.40679B
                                 CALL.4 #06641        
                                 MOVE.W A,R1          
                                 CLR.A C              
                                 MOVE.P1 #5,C         
                                 CALL.3 #05B7D        
                                 MOVE.W R1,C          
                                

   Move 4 nibbles forward:
                                Ŀ
04[right]       PC=PC+4         @:059D5 P:0 CH ST:218 
                                CLR.AA
                                 CALL.4 #06641        
                                 MOVE.W A,R1          
                                 CLR.A C              
                                 MOVE.P1 #5,C         
                                 CALL.3 #05B7D        
                                 MOVE.W R1,C          
                                
   Notice that we didn't really advance the PC by one
   full instruction, which means that the PC now points
   two nibbles into the offset of the previous CALL
   instruction.

   Set the PC back to 059D1 and switch to the memory
   screen:
                                Ŀ
059D1[ENTER]    PC=#059D1       059A0:56113680913420CC
                                059B0:4E0156716FCC56FD
[E]             Memory dump,    059C0:015B38D5E0101D95
                screen 5        059D0:0E4CD08E46C0101
                                059E0:D230574911191443
                                059F0:4E4A201101311456
                                05A00:12280A50143174E7
                                05A10:8E58D01311741431
                                

   Move 16 nibbles back:
                                Ŀ
[up]            PC=PC-#10h      05990:3A6E80D0F40D4F01
                                059A0:56113680913420CC
                                059B0:4E0156716FCC56FD
                                059C0:05B38D5E0101D95
                                059D0:08E4CD08E46C0101
                                059E0:D230574911191443
                                059F0:4E4A201101311456
                                05A00:12280A50143174E7
                                

   Set the PC back to 059D1 and switch to the
   Instructions screen:
                                Ŀ
059D1[ENTER]    Back to #59D1h  @:059D1 P:0 CH ST:218 
                                CALL.4679B
[F]             ML instructions  CALL.4 #06641        
                                 MOVE.W A,R1          
                                 CLR.A C              
                                 MOVE.P1 #5,C         
                                 CALL.3 #05B7D        
                                 MOVE.W R1,C          
                                

   Jump to next instruction:
                                Ŀ
[NXT]           Forward one     @:059D7 P:0 CH ST:218 
                instruction     CALL.406641
                                 MOVE.W A,R1          
                                 CLR.A C              
                                 MOVE.P1 #5,C         
                                 CALL.3 #05B7D        
                                 MOVE.W R1,C          
                                 MOVE.A C,@D0         
                                

   Set the mark and advance three instructions:
                                Ŀ
[x]             Set mark        @:059D7 P:0 CH ST:218 
                                MOVE.P15,C
03[NXT]         Forward 3        CALL.3 #05B7D        
                instructions     MOVE.W R1,C          
                                 MOVE.A C,@D0         
                                 MOVE.P5 #02A4E,C     
                                 MOVE.W R0,A          
                                 MOVE.A A,D1          
                                

   Swap the mark and the PC:
                                Ŀ
[+/-]           Toggle mark,    @:059D7 P:0 CH ST:218 
                PC              CALL.406641
                                 MOVE.W A,R1          
                                 CLR.A C              
                                 MOVE.P1 #5,C         
                                 CALL.3 #05B7D        
                                 MOVE.W R1,C          
                                 MOVE.A C,@D0         
                                

   The arrow keys are most useful for moving around in
the memory dump, but can also be used to arbitrarily
increment and decrement the PC to shift the instruction
stream by single nibbles. The mark commands are useful
for temporarily remembering an address that you wish to
return to later.
@@Quit
Terminating the Program


   There are four ways to leave the MLDB. The first two
listed below continue RPL execution at the next token in
the thread. If invoked from the LIBRARY MLDL menu,
control is returned to normal calculator operation. The
third method of leaving the MLDB, also listed below,
warmstarts the calculator by performing a system reset
(no variables are lost; same as ON-C). The fourth method
is to allow the program to run to completion by pressing
EVAL (described in the next section).

        [<==]   (Delete key)
                Exits.

        [DEL]   Restores system registers to the state
                they were in when the debugger was
                entered. This is useful if you would need
                to exit in the middle of your program and
                the system registers contain random data.
                It does nothing if ARG was supplied, in
                effect acting as an ARG cancellation key.

        [1/X] [1/X]
                Panic exit. If you know the machine will
                crash when you exit, such as could be the
                case if memory has been reconfigured or
                trashed. Resets the calculator by a "warm
                start" (same as ON-C; no variables are
                lost).
@@SST & Run
Program Stepping and Running


The program can either be single-stepped instruction by
instruction, or allowed to run free, which means that the
program will run without interference until it completes
or encounters a breakpoint. Single-stepping can be either
shallow or deep. A shallow step is one where CALLs are
stepped as a single instruction (similar to the SST
command). A deep step follows CALLs into subroutines
(similar to the SST command). Both shallow and deep
stepping can be given ARGs, in which case the ARG
determines the number of instructions to be stepped. If
multiple instructions are stepped, then they are
susceptible to breakpoints. The table below lists the
keys that control program execution.

A single-step of more than one instruction is sensitive
to the ON key. Pressing ON during a single-step of more
than one instruction will halt execution. During
execution, PICT is displayed unless it has been purged, a
behavior which can be disabled (see Option 5, below).

        [+]     Deep Single-steps one (or ARG)
                instruction(s), pointed to by the PC.
                Follows CALLs. If ARG, then also checks
                for breakpoints and displays PICT until
                done.

        [-]     Shallow Single-steps one (or ARG)
                instruction(s). Same as [+], but does
                not follows CALLs; instead, the program
                halts when it returns from the CALL.
                Subroutines are single-stepped as if they
                were single instructions.

        [.]     Redraws the display but otherwise does
                nothing.

        [EEX]   Display PICT until released.

        [EVAL]  Continue execution, running until program
                completes, breakpoint is reached, or a
                broken [-] CALL execution completes.
                Displays PICT while program runs.

Example, Program Completion:

           Start with the stack display, in HEX mode, in
        the LIBRARY MLDL menu. Only the relevant lines of
        the stack display are included in the example
        below. #3244h is the address of the System RPL
        DROP command.

                                        
Keys            Comments         Display following keys
                    

HEX STD         Set up modes


2 1 #3244h      Enter two dummy 3:                   2
[ENTER]         arguments for   2:                   1
                DROP, and the   1:             # 3244h
                address of the  
                DROP command


                                Ŀ
[MLDB]          Invoke MLDB on  @:03249 P:0  H ST:218 
[F]             the DROP PMC    #ADD.A##5,D1##########
                and choose the   INC.A D              
                instruction      MOVE.A @D0,A         
                screen           ADD.A #5,D0          
                                 JUMP.A @A            
                                 MOVE.A C,B           
                                 MOVE.1 #3,P          
                                

   The DROP PMC consists of only the first 5 instructions.
Executing the JUMP @A instruction will cause the program
to reach completion. Allow the program to complete
without interference:

[EVAL]          Allow program   1:                   2
                to run freely;  
                the 1 is dropped.
@@Breakpoints
Breakpoints


   The MLDB maintains a breakpoint table of eight slots.
Each slot consists of an address and a counter, both of
which are displayed when the MTH key is pressed (see
below). The address is 20 bits and the counter is eight
bits. Breakpoints only work in RAM, although they can be
set in ROM and triggered by multi-instruction
single-steps.

    When a breakpoint is triggered, its counter is
incremented; if after the increment it is negative
(80-FF), the program will continue. Setting a negative
counter is therefore a way of instructing MLDB to "ignore
this breakpoint N times" where N is in the range 01-7F
hexadecimal. If the counter is positive, the program is
halted with a "Breakpoint Stop" or "Breakpoint Trap"
message, depending on whether the breakpoint was
triggered during a single-step or free run, respectively.
Positive counters indicate how many times the program has
halted at a specific breakpoint.

Breakpoints are accessible via three keys:


        [MTH]   Switch to breakpoint table screen. Any
                entry at the current PC will be displayed
                in reverse video.

        [PRG]   Set breakpoint address. Waits for a
                further key, 1-8, which specifies the
                breakpoint whose address is to be set.
                ARG is the new address value. If no ARG
                is entered, then the entire breakpoint is
                cleared (its address and counter are both
                zeroed out).

        [STO]   Set breakpoint counter. Waits for a
                further key, 1-8, which specifies the
                breakpoint whose counter is to be set.
                ARG is the new counter value. The counter
                is cleared if no ARG is entered. Only the
                low 8 bits of ARG are used.

Example, Breakpoints:

Keys            Comments         Display following keys
                    

                                Ŀ
059D1[ENTER]    PC=59D1         CALL.4 #0679B         
[A]             Screen 1         8E4CD0               
                                @:059D1 P:0 CH ST:218 
                                A:000CC C:77794       
                                B:729A9 D:00F96 HST:2 
                                D0:409C1/9540A8240BC9 
                                D1:77799/000000000000 
                                RST:00000:00000:00000 
                                


                                Ŀ
[MTH]           Breakpoint       1:00000  00          
                table screen     2:00000  00          
                                 3:00000  00          
                                 4:00000  00          
                                 5:00000  00          
                                 6:00000  00          
                                 7:00000  00          
                                 8:00000  00          
                                


                                Ŀ
059D1[PRG]1     Set             1:059D100
                breakpoint 1     2:00000  00          
                at #59D1h        3:00000  00          
                                 4:00000  00          
                                 5:00000  00          
                                 6:00000  00          
                                 7:00000  00          
                                 8:00000  00          
                                


   The inverse bar in the display above indicates that the
breakpoint is set at the current PC.


                                Ŀ
[F]             Examine next    @:059D1 P:0 CH ST:218 
                7 instructions   CALL.4 #0679B        
                                 CALL.4 #06641        
                                 MOVE.W A,R1          
                                 CLR.A C              
                                 MOVE.P1 #5,C         
                                 CALL.3 #05B7D        
                                 MOVE.W R1,C          
                                


[MTH]           Back to breakpoint
                table screen

                                Ŀ
06641[PRG]5     Set             1:059D100
                breakpoint 5     2:00000  00          
                at #6641h        3:00000  00          
                                 4:00000  00          
                                 5:06641  00          
                                 6:00000  00          
                                 7:00000  00          
                                 8:00000  00          
                                


                                Ŀ
040[+]          Single-step 64   1:059D1  00          
                instructions     2:00000  00          
                (remember that   3:00000  00          
                ARG is always    4:00000  00          
                entered in hex) 5:06641+01
                                 6:00000  00          
                                 7:00000  00          
                                 8:00000  00          
                                


   We never really got as far as 64 instructions. Instead
we ran into the breakpoint at #6641h and stopped there,
with a "Breakpoint Stop" message appearing briefly. The
breakpoint table above tells us why we stopped, and that
it is our first stop here. Setting breakpoints and
single-stepping a large number of instructions is the
only way to use breakpoints in ROM.


                                Ŀ
[STO]5          Clear            1:059D1  00          
                breakpoint 5's   2:00000  00          
                counter          3:00000  00          
                                 4:00000  00          
                                5:0664100
                                 6:00000  00          
                                 7:00000  00          
                                 8:00000  00          
                                

More About Breakpoints


   A breakpoint is actually a CALL.A to an entry in the
MLDB. When the breakpoint is reached, control is
transfered to the breakpoint trap handler in the MLDB. It
finds the location of the breakpoint on the return stack
(RSTK), looks it up in the breakpoint table, and proceeds
as outlined above. Since a CALL.A instruction occupies 7
nibbles of memory, problems can arise when the program
contains a sequence like this:


        point:  brcc    foo             ; 3 nibbles
                inc.a   c               ; 2 nibbles
        foo:    inc.a   c               ; 2 nibbles
                dec.a   a               ; 2 nibbles


   Picture what would happen if a breakpoint is set at
`point.' It uses up 7 nibbles of memory, and thus
overwrites the BRCC, subsequent INC, and the INC at
`foo.' Assume another piece of the program makes a jump
to `foo.' This will result in a jump into the last two
nibbles of the breakpoint instruction! The program is
bound to behave erratically; if we're lucky this means
mysterious results, but if we're unlucky, the calculator
will crash and wipe its memory.

   Here's how this problem is avoided.

   During a [+] single-step of multiple instructions
(actually, any single-step with an ARG will do), the
breakpoints are never actually inserted into the program.
Instead, each consecutive PC is matched against the
breakpoint table, and if a breakpoint is set at exactly
that address, the single-stepping will stop. This usage
of breakpoints is entirely safe and works under all
conditions. It can, of course, be used for ROM as well as
RAM programs. The drawback is execution speed, although
the [-] stepping variant is usually faster than the [+]
variant. Graphics and other CPU-heavy applications take
seemingly forever to run. There is no simple solution -
you must take the 7-nibble limit into consideration when
writing such programs. Insert NOPs at places where you
know you will want to insert breakpoints.

   The [-] single-step does not follow CALLs. It executes
the entire subroutine as if it were one single
instruction. When it returns, control returns to MLDB,
which then proceeds with the next instruction in
sequence, the one following the CALL. Time-consuming
functions like graphics routines can be placed in
separately debugged and verified subroutines, and the
main program calling these routines debugged with [-].
This will generally shorten stepping time.

   During [-] single-step, when a subroutine that is
allowed to run free returns or encounters a breakpoint,
the program halts. The return address *into* MLDB will be
on top of the return stack if it encountered a
breakpoint. Pressing [EVAL] to continue at this point
will cause the subroutine to continue running free, until
it again reaches a breakpoint or returns, at which point
it returns to MLDB and continues its [-] single-step. The
subroutine can also be single-stepped when it has
encountered a breakpoint, but *only* until it returns to
the caller, at which point it should be allowed to return
by pressing EVAL.
@@Watchpoints
Watchpoints


The MLDB keeps track of watchpoints in the watchpoint
table, which consists of eight entries. Each entry can be
set to any arbitrary address, which will appear as a
memory dump line (described above) in the watchpoint
table screen (described above). By default, the addresses
are set to 00000. Watchpoints are useful for monitoring
memory contents.

Watchpoints are accessed through the VAR key:

VAR     If no ARG: switch to the watchpoint table screen.

VAR     If ARG: set watchpoint. Expects a further key,
        1-8, which specifies the watchpoint to set. ARG
        is the new watchpoint address value. Watchpoints
        are cleared by setting them to 00000.
@@Options
Options


There are three special options available, numbered 3, 4
and 5.

Option 3 is used to switch to ASCII mode, which aids in
debugging programs that do any kind of text processing.
Since bytes take up two nibbles, ordinary even-address-
aligned memory dumps are not useful for examining ASCII
characters in memory when they happen to begin at odd
addresses.

Option 4 toggles the alignment between even addresses
(the default) and odd.

Option 5 toggles the automatic display of PICT during
program execution.

Notice that since ASCII mode affects ARG entry and all
other integers displayed (except instructions), it is
only intended to be briefly toggled in and back out. The
same applies to the memory dump alignment shift. All
options are reset when the MLDB is initially invoked.

The options are invoked with the CST key:

CST 3    Toggle ASCII mode. All numerical data (except in
         instructions) will appear as 7-bit ASCII
         characters. Nonprintable characters appear as
         dots (.), and characters with the high bit set
         will appear in reverse video.

CST 4    Toggle memory dump alignment. Affects only the
         memory dump; instead of the memory dump lines
         being evenly aligned, it will be oddly aligned,
         and vice versa.

CST 5    Toggle automatic PICT display during program
         execution.
@@Server Modes
MLDB Server Modes


User flags 32 and 33 control the MLDB mode:


                         Server,        Server,
         Flag  Local   Interactive     Protocol
        
          32   Clear       Set            Set
          33   Clear      Clear           Set


   The normal mode of operation, as described in the
previous sections, is Local mode. The other two modes are
referred to as Server Modes, and are:

- Interactive Mode, in which commands (see Server Mode
Commands, below) are entered on a dumb ASCII terminal or
emulator with full editing (see Server Modes Command
Entry, below); and

- Protocol Mode, in which the same commands are accepted
as in Interactive Mode, except no prompts are printed,
and commands are not echoed during reception. The
Protocol Mode is intended for communication with software
on the development system.

   You must set up I/O in the HP48 before invoking the
MLDB in a server mode; see the HP48 manual for details.
The MLDB server modes always communicate over the wire,
effectively ignoring the state of system flag -33 (I/O
device).
@@Server Cmds
MLDB Server Mode Commands


   Commands can be entered in response to the ``*''
prompt in interactive mode. Commands can be sent at any
time in protocol mode. Generally, excessive input is
ignored, as are unrecognized commands or commands with
invalid arguments. Command lines of up to 80 characters
can be entered. Below is the list of the 18 recognized
commands. The command name is first, and optional
arguments are enclosed in square brackets. Don't type the
brackets when entering the commands; they are used in the
table merely to indicate that the argument is optional.

= <addr>        Set the PC to <addr>.
                <addr> is in the range 00000-FFFFF.

+ <offs>        Add <offs> to PC.
                <offs> is in the range 00000-FFFFF.

- <offs>        Subtract <offs> from PC.
                <offs> is in the range 00000-FFFFF.

n [<n>]         Advance PC forward <n> instructions. If
                no <n> is supplied, the PC is advanced
                one instruction.

s [<n>]         Single-step <n> instructions. Same as the
                [+] key in Local Mode. If no <n> is
                entered, one instruction is stepped. A
                single-step of more than one instruction
                can be interrupted by pressing any key,
                which is ignored.

S [<n>]         Single-step <n> instrutions, but don't
                follow CALLs. Same as the [-] key in
                Local Mode. If no <n> is entered, one
                instruction or CALL is is stepped. A
                single-step of more than one instruction
                can be interrupted by pressing any key,
                which is ignored.

c               Continue free-run execution until the
                program completes or a breakpoint is
                encountered. When the program completes,
                "Exit" is printed and MLDB exits.

t               Terminate. Exit with current registers.

T               Terminate. Exit with system registers set
                up exactly as they were when MLDB was
                invoked.

R               Reset.

r               Print registers. The HEX/DEC mode is
                printed as "HD:0" or "HD:1". A zero means
                that HEX mode is active, a one means that
                DEC mode is active.

i [<n>] [<addr>]
                Print instructions. <n> instructions are
                printed, starting at <addr>. The first
                argument is always <n> and the second is
                <addr>. If no <addr> is entered, the
                current PC is assumed. If <n> isn't
                entered, one (the next) instruction is
                printed. <n> and <addr> are both in the
                range 00000-FFFFF.

x [<n>] [<addr>]
                Print memory contents. <n> words of 16
                nibbles are printed, starting at <addr>,
                each on a separate line. The first
                argument is always <n> and the second is
                <addr>. If no <addr> is entered, the
                current PC is assumed. If <n> isn't
                entered, one (the next) word is printed.
                <n> and <addr> are both in the range
                00000-FFFFF.

a [<n>] [<addr>]
                Print memory contents in ASCII. <n> words
                of 32 nibbles are printed as ASCII
                characters, starting at <addr>, each
                consecutive word on a separate line. The
                first argument is always <n> and the
                second is <addr>. If no <addr> is
                entered, the current PC is assumed. If
                <n> isn't entered, one (the next) word is
                printed. <n> and <addr> are both in the
                range 00000-FFFFF.

z               Print the return stack (the RSTK).

db <n> [<addr>] Set breakpoint <n> at <addr>. If <addr>
                is absent, the breakpoint is cleared.
                <addr> is in the range 00000-FFFFF. <n>
                must be in the range 1-8.

hb <n> [<cntr>] Set breakpoint <n> counter to <cntr>. If
                <cntr> is absent, the counter is set to
                00. <cntr> is in the range 00-FF.
                <n> must be in the range 1-8.

lb              List breakpoints.
@@Cmd Entry
MLDB Server Modes Command Entry


   In both Interactive and Protocol Modes, input can be
edited, although no echo or response can be detected in
Protocol Mode. The following table may be of help when
you try to locate the editing keys on your keyboard.
After 80 characters have been typed, any further entry
(except the editing keys listed below) is ignored.


Backspace, Delete,      Erase the last character entered.
or Rubout

Control-W               Erase the last word entered.

Control-U or            Erase the entire line.
Control-X

Control-R               Rewrite input.

Return, Enter, or       Execute command entered.
Control-M


Example, An MLDB Interactive Mode Session


Connect the HP48 to your dumb terminal or computer.

Type this into the HP48's command line and then press
ENTER:

1  2  #3223h  MLDB

First, we are greeted with a header:

    MLDL 1.06A
    Copyright (c) 1991 Jan Brittenson

We will now watch SWAP work on the 1 and 2 on the stack.

Note, however, that in reality output will rarely
resemble the perfection of this example, because here we
"just happened" to know in advance the number of
instructions to be listed, which almost never happens in
real-world debugging sessions.

Let's first take a look at the SWAP PMC by typing the
command shown after the "*" prompt:

        * i 9
        MOVE.A @D1,C
        ADD.A #5,D1
        MOVE.A @D1,A
        MOVE.A C,@D1
        SUB.A #5,D1
        MOVE.A A,@D1
        MOVE.A @D0,A
        ADD.A #5,D0
        JUMP.A @A

Then the registers:

        * r
        CY:0
        P:0
        PC:03228
        A:0000000644403223
        B:0960000000074FB3
        C:0000000000075FBB
        D:0000000000000335
        R0:000000000007BCA5
        R1:0000000644403228
        R2:00000000000505C6
        R3:0000000644400001
        R4:00015074EE274F20
        D0:7C1A5
        D1:75FC0
        ST:000
        HST:2
        HD:0

So stack level 1 is at 75FC0. Examine level 1.

        * x 1 75fc0
        75FC0:ED2A29C2A2000000

Which is object 2A2DE. Examine this object.

        * x 2 2a2de
        2A2DE:3392000000000000
        2A2EE:0002033920000000

Which is a real (type prefix 2933), the constant 2. Let's
step a few instructions.

        * i
        MOVE.A @D1,C
        * s
        * i
        ADD.A #5,D1
        * s
        * i
        MOVE.A @D1,A
        * s
        * i
        MOVE.A C,@D1
        * s
        * i
        SUB.A #5,D1
        * s
        * i
        MOVE.A A,@D1
        * s

Now, what do we have left of the SWAP PMC?

        * i 3
        MOVE.A @D0,A
        ADD.A #5,D0
        JUMP.A @A

Finally, we step a goodly chunk of instructions. That way
we can be sure that the program completes.

        * s 100
        Exit

We're done. The HP-48 stack now reads "2" in level 2, and
"1" in level 1.
@@Messages
Messages


Stopped

    Appears for about a second at the top of the screen.
    Indicates that a single-step of multiple instructions
    was interrupted by pressing the ON key.

Breakpoint Stop

    Appears for about a second at the top of the screen.
    Indicates that a single-step of multiple instructions
    encountered a breakpoint.

Breakpoint Trap

    Appears for about a second at the top of the screen.
    Indicates that the program encountered a breakpoint
    during free run. This can occur either during a CALL
    executed with the [-] key or a free run initiated
    with the EVAL key.

Fatal Error:
Data Lost

    Indicates that the 'MLDLpar' variable was corrupted
    or purged, either directly or indirectly, by the
    program being debugged. No recovery is possible.
    Press any key to reset (same as ON-C).

Fatal Error:
ROM Card Failure

    Indicates that an attempt was made to use the "B"
    version of the MLDL from a write-enabled RAM card.
    Press any key to reset, then either (a) switch the
    RAM card to write-protected, (b) burn it into an OTP,
    EPROM, or the like, and run it from there, or (c)
    purge the MLDL and replace it with the "A" version
    which does run in write-enabled RAM cards.

Fatal Error:
RAM Card Failure

    Indicates that an attempt was made to use the "A"
    version of the MLDL from a write-protected RAM card,
    OTP, EPROM, or the like. Press any key to reset, then
    either (a) switch the RAM card to write-enabled, or
    (b) purge the MLDL and replace it with the "B"
    version which does run in write-protected RAM cards,
    OTPs, EPROMs, and the like.
@@Warnings
Some MLDB System Considerations


   The debugger (MLDB) has been designed in such a way
that it will not alter any static system data or depend
on the precise machine configuration (assuming that the
automatic displaying of PICT has been disabled). The only
system data it modifies is the keyboard buffer, since it
relies on the system to respond to the keyboard interrupt
and manage the buffer. Testing has shown that
interfering with this results in poor reliability. Still,
there are three instructions the debugger will refuse to
single-step:


RESET
          The effect of this would be the same as ON-C.

CLRB #F,ST

          Executing this instruction would lock up your
          calculator since it would disable all I/O, most
          notably the keyboard.

INTOFF
          This would also lock up the keyboard.

   Apart from the aspects outlined above and some system
RPL code to do argument type checking, the debugger is
self-contained.


A Word of Caution


   The [-] key lets you complete an entire CALL. But
beware: the return stack is replaced by one that will
cause the called routine to return to the debugger.
Therefore the routine called cannot rely on specific
return stack contents, or remove return addresses from
the stack, either of which will invariably result in a
system crash. One example of a ROM routine that actually
does this is 0CD8E, which jumps to a location in the
bank-switched ROM usually hidden behind user RAM. Most of
the trig and log functions are actually located in this
hidden ROM.

Despite the effort put into avoiding system collisions,
the HP48 still remains a largely unprotected system.
The debugger - or other parts of the MLDL - can still be
overwritten, which may result in memory loss. Since the
MLDL is stored as a library in a port, it is not
susceptible to general memory allocation, such as dynamic
memory allocation or system display GROB allocations. On
the other hand, storing another library in the same port
may cause it to move - extreme caution is therefore
advisable when single-stepping PMC that alters stored
port data. If you are stepping a port store block copy by
means of either [+] or [-], then the MLDL may be
overwritten. If you're using [-] to call a block copy
routine within a similar context, then the library may
have moved and the subsequent return will cause a system
crash and possibly memory corruption.

   Single-stepping a machine code program is in no way
less dangerous than allowing it to run uncontrolled. It
merely gives you some control over what happens between
instructions. It can even be more dangerous; hardware may
break if left in certain configurations for a period of
time, which may be a fraction of a second (most notably
the LCD and the IR LED). So if you are going to
single-step parts of the system ROM, you should be aware
of this risk, although the author at this time has never
actually heard of this occurring. In no way will the
author or distributors of the MLDL or anybody else accept
any responsibility or liability for such damage,
regardless of its nature and extent.

   The MLDL is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
@@MLPR=========
[MLPR] ==================================================

Disassembles and prints ML programs, non-stop until
interrupted. Accepts the same arguments as MLDB, except
@#3a81 and #3ac0 which are not recognized. The program is
printed to the current print device, IR or wire. In case
of problems, first check your PRTPAR - see your HP48
manual for details.

Each printed line consists of a mnemonic preceded by the
address. No opcode is included, since it normally is of
little interest.

MLPR is not too intelligent; it disassembles starting at
the address specified (or at the beginning of the code
onject) onward until you press ON to stop it. ML1
(described below) can be used to build your own custom
disassembler with more intelligence. Due to this
limitation, MLPR is not really suitable to be called from
a program. Its intended use is to quickly list machine
code on a printer or to the serial port. If passed a code
object, the code object should not reside in TEMPOB;
store it in a variable and recall it before invoking
MLPR.
@@ML1==========
[ML1] ===================================================

   Disassembles one ML instruction; allows you to build
your own disassemblers with its own special-purpose user
interface. It takes a binary integer in level one, and
returns two values; in level 2 the mnemonic form preceded
by the address, and in level one the address of the next
instruction. Thus it is a simple task to make a number of
consecutive calls to ML1. MLOPC (described below) can be
used to extract the opcode as a string of hexadecimal
digits. Extracting the mnemonic from the string is
trivial, since it will always be of the form:

        "xxxxx: m"

where xxxxx is a five-digit address followed by a colon
and a blank. The last part of the string, m, is the
mnemonic.
@@MLOPC========
[MLOPC] =================================================

   Returns opcode as a string of hexadecimal digits.
Expects two binary integers - the first address in level
2 and the final address plus one in level 1. Useful for
creating the opcode field in a custom disassembler.
Example, MLOPC:

        #59D1 #59D7 MLOPC  -->  "8E4CD0"

The opcode size is limited to 255 digits.
@@Cmd Summary
MLDL COMMAND SUMMARY


Ŀ
                                                       
 ABOUTMLDL     Displays version and copyright screen   
                                                       
Ĵ
                                                       
 MLDB          Saturn Machine Language Debugger        
                                                       
                       obj     --> any1 ... anyN       
                                                       
Ĵ
                                                       
 MLPR          Print Machine Language Program          
                                                       
                       obj     --> obj                 
                                                       
Ĵ
                                                       
 ML1           Single-Instruction ML Disassembler      
                                                       
                     #address  --> "instruction" #next 
                                                       
Ĵ
                                                       
 MLOPC         Machine Language Instruction Opcode     
                                                       
          #address1 #address2  --> "hex digits"        
                                                       

@@Kbd Summary
MLDB LOCAL MODE KEYBOARD SUMMARY


Screens         No ARG                  ARG
                       

[A]             General CPU State
[B]             Arithmetic registers
[C]             Data registers
[D]             Return stack (RSTK)
[E]             Memory dump
[F]             Instruction stream
[MTH]           Breakpoint table        Breakpoint table

ARG entry

[0]             Begins ARG entry
0-9, A-F        Hex digits
[+/-]           2's complement
[<==]           Shift right one digit
[DEL]           Cancel

Moving around

[ENTER]         Ignored                 PC=ARG
[left]          PC=PC-1                 PC=PC-ARG
[right]         PC=PC+1                 PC=PC+ARG
[up]            PC=PC-16                PC=PC-16*ARG
[down]          PC=PC+16                PC=PC+16*ARG
[x]             MARK=PC                 MARK=ARG
[+/-]           MARK <-> PC             MARK <-> PC
[NXT]           Advance one             Advance ARG
                instruction             instructions

Breakpoints (b = 1 - 8)

[MTH]           Breakpoint table        Breakpoint table
                screen                  screen

[PRG]b          Clear breakpoint b      Set breakpoint b
                address & counter       address to ARG

[STO]b          Clear breakpoint b      Set breakpoint b
                counter                 counter to ARG

Program execution

[+]             Single-step one         Single-step ARG
                instruction             instructions

[-]             Single-step one         Single-step ARG
                instruction, do         instructions; do
                not follow CALLs        not follow CALLs

[EVAL]          Let program run until   Ignored
                completed, or until
                breakpoint
@@XLIB numbers
MLDL XLIB TABLE


The library number is 444 hexadecimal, which is 1092
decimal.


        Command         Number
        
        Version         1092 0
        MLDB            1092 1
        MLPR            1092 2
        ML1             1092 3
        MLOPC           1092 4
